﻿using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;

    public class MouseHook
{


        public static int WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        WM_RBUTTONDOWN = 0x0204,
        WM_RBUTTONUP = 0x0205;

     static private USER32.HookProc MouseHookDelegate = null;
     static private IntPtr hook;
     static private MouseClickedCallback delegato;

     public delegate void MouseClickedCallback();

     public MouseHook(MouseClickedCallback callback)
     {
         MouseHook.MouseHookDelegate = new USER32.HookProc(MouseHook.MouseCallback); // Inizializzo il delegato
         using (Process curProcess = Process.GetCurrentProcess())
         using (ProcessModule curModule = curProcess.MainModule)

             hook = USER32.SetWindowsHookEx(USER32.HookType.WH_MOUSE_LL, MouseHook.MouseHookDelegate, GetModuleHandle(curModule.ModuleName), 0); // Hook Globale del Mouse!!!
         
         delegato = callback;
     }

     private static int MouseCallback(int code, IntPtr wParam, IntPtr lParam)
     {
    
        if (code < 0) {
            //you need to call CallNextHookEx without further processing
            //and return the value returned by CallNextHookEx
            return USER32.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
        }

       // System.Console.WriteLine("Nuovo hook raccolto codice: "+ wParam.ToInt32());
        if (code>= 0 && wParam.ToInt32().Equals(WM_RBUTTONDOWN)) // ho cliccato con il mouse tasto destro
        {
            delegato.Invoke(); // richiamo la funzione di callback
            return USER32.CallNextHookEx(IntPtr.Zero, -1, wParam, lParam);
        }
        //return the value returned by CallNextHookEx    
         return USER32.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
    }
    

     public static void UnHook()
     {
         USER32.UnhookWindowsHookEx(MouseHook.hook);             // chiamo una funzione
     }

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
     private static extern IntPtr GetModuleHandle(string lpModuleName);
}
